#ifndef FRAMEQUEUE_H
#define FRAMEQUEUE_H
#include "ffinc.h"
#include "PacketQueue.h"
#include <iostream>
#include <memory>
using namespace std;
/**
 * @brief Frame循环队列
 */
class FrameQueue
{
public:
    struct Frame {
        AVFrame *frame;         // 指向数据帧
        uint32_t serial;        // 帧序列，在seek的操作时serial会变化
        double pts;             // 时间戳，单位为秒
        double duration;        // 该帧持续时间，单位为秒
        int64_t	pos;            // 该帧在输入文件中的字节位置
        int	format;             // 对于声音则为(enum AVSampleFormat)
        int	uploaded;           // 用来记录该帧是否已经显示过？
    };
public:
    FrameQueue();
    ~FrameQueue();

public:
    /**
     * @brief 队列初始化
     * @param pktq: 媒体包队列指针
     * @param max: 队列的大小
     * @param keep_last: 是否保留最后一次播放的帧
     * @return
     */
    int frame_queue_init(shared_ptr<PacketQueue> pktq, int max, bool keep_last);
    /**
     * @brief 销毁队列
     */
    void frame_queue_destory();
    /**
     * @brief 发送唤醒信号
     */
    void frame_queue_signal();
    /**
     * @brief 向队列尾部申请一个可写的帧空间(阻塞)
     */
    Frame *frame_queue_peek_writable();
    /**
     * @brief 向尾部插入一帧数据
     */
    void frame_queue_push();
    /**
     * @brief 从队列头部读取一帧
     * @note 只读取不删除，若无帧可读则等待。
     */
    Frame *frame_queue_peek_readable();
    /**
     * @brief 释放数据并更新读索引及size
     */
    void frame_queue_next();
    /**
     * @brief 释放资源
     */
    void frame_queue_unref_item(Frame *vp);

private:
    Frame queue[FRAME_QUEUE_SIZE];      // FRAME_QUEUE_SIZE  最大size, 数字太大时会占用大量的内存，需要注意该值的设置
    uint32_t rindex;                    // 读索引。待播放时读取此帧进行播放，播放后此帧成为上一帧
    uint32_t windex;                    // 写索引
    uint32_t size;                      // 当前总帧数
    uint32_t maxSize;                   // 可存储最大帧数
    bool keep_last;                     // = true说明要在队列里面保持最后一帧的数据不释放，只在销毁队列的时候才将其真正释放
    uint32_t rindex_shown;              // 初始化为0，配合keep_last=1使用
    mutex _mutex;                       // 互斥量
    condition_variable _condition;      // 队列内部信号量，用于读、写线程相互通知
    shared_ptr<PacketQueue> pktq;       // 数据包缓冲队列
};

#endif // FRAMEQUEUE_H
